package com.lc.executor.impl;

import com.lc.entity.SqlEntity;
import com.lc.entity.SqlParam;
import com.lc.executor.Executor;
import com.lc.handler.ResultHandler;
import com.lc.resolver.ParamResolver;
import com.lc.type.TypeHandler;
import com.lc.type.TypeHandlerRegistry;


import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;


public class DefaultExecutor implements Executor {

    private TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();

    private ResultHandler resultHandler = new ResultHandler();

    private ParamResolver paramResolver = new ParamResolver();

    @Override
    public Object executeQuery(Class<?> returnType, Method method, Object[] args) throws ClassNotFoundException,
            SQLException, InstantiationException, IllegalAccessException {
        Connection conn = null;
        try {
            conn = getConn();
            SqlEntity sqlEntity = paramResolver.resolveSqlParam(method);
            if (returnType != null && !"java.util.List".equals(returnType.getName())) {
                List<Object> list = selectList(conn, sqlEntity, args);
                if (list != null && list.size() > 0) {
                    return list.get(0);
                } else {
                    return null;
                }
            } else {
                return selectList(conn, sqlEntity, args);
            }
        } finally {
            conn.close();
        }
    }

    @Override
    public int executeInsert(Method method) {
        Connection conn = null;
        try {
            conn = getConn();
            SqlEntity sqlEntity = paramResolver.resolveSqlParam(method);

        } finally {

        }
        return 0;
    }

    @Override
    public int executeUpdate() {
        return 0;
    }

    @Override
    public int executeDelete() {
        return 0;
    }


    private List<Object> selectList(Connection conn, SqlEntity sqlEntity, Object[] args) throws SQLException,
            IllegalAccessException, InstantiationException, ClassNotFoundException {
        List<Object> result = new ArrayList<>();
        PreparedStatement ps = conn.prepareStatement(sqlEntity.getSql());
        setParamValue(ps, sqlEntity, args);
        ResultSet rs = ps.executeQuery();

        while (rs != null && rs.next()) {
            Object target = resultHandler.getResult(sqlEntity.getReturnType(), rs);
            result.add(target);
        }
        return result;
    }


    public void setParamValue(PreparedStatement ps,
                              SqlEntity sqlEntity, Object[] args) throws SQLException {
        List<SqlParam> sqlParams = sqlEntity.getSqlParams();
        for (int i = 0; i < sqlParams.size(); i++) {
            SqlParam sqlParam = sqlParams.get(i);
            if (sqlParam != null) {
                Class<?> paramType = sqlParam.getParamType();
                TypeHandler typeHandler = typeHandlerRegistry.findTypeHandler(paramType);
                typeHandler.setStatementValue(ps, i + 1, args[i]);
            }
        }
    }


    public static Connection getConn() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/xunwu", "root", "1234");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}
